﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace CommonLibrary.Helpers
{
    public static class TimeHelper
    {
        /// <summary>
        /// 自然时间获得时间坐标
        /// </summary>
        /// <param name="dateTime"></param>
        /// <param name="planStartClock"></param>
        /// <returns></returns>
        public static int GetTimePos(this DateTime dateTime)
        {
            int planStartClock = Sys.PlanStartHourCnt;
            var totalMinutes = (int)dateTime.TimeOfDay.Subtract(new TimeSpan(planStartClock, 0, 0)).TotalMinutes;
            return dateTime.Hour >= planStartClock ? totalMinutes : totalMinutes + 24 * 60;
        }
        /// <summary>
        /// 时间坐标获得自然时间
        /// </summary>
        /// <param name="minutePos"></param>
        /// <param name="planStartClock"></param>
        /// <returns></returns>
        public static DateTime GetDateTimeByMinute(this int minutePos)
        {
            int planStartClock = Sys.PlanStartHourCnt;
            return DateTime.Today.AddHours(planStartClock).AddMinutes(minutePos);
        }

        //public static DateTime GetDateTimeByHour(this int hourPos, int planStartClock = Sys.PlanStartHourCnt)
        //{
        //    return DateTime.Today.AddHours(hourPos >= planStartClock ? hourPos - planStartClock : hourPos - planStartClock + 24);
        //}

        /// <summary>
        /// 自然小时时间获得时间坐标
        /// </summary>
        /// <param name="hourPos"></param>
        /// <param name="planStartClock"></param>
        /// <returns></returns>
        public static int GetTimePosByHour(this int hourPos)
        {
            int planStartClock = Sys.PlanStartHourCnt;
            var hourToStart = hourPos - planStartClock;
            return (hourPos >= planStartClock ? hourToStart : hourToStart + 24) * 60;
        }
        /// <summary>
        /// 自然时间，非法值-1
        /// </summary>
        /// <param name="time"></param>
        /// <param name="planStartClock"></param>
        /// <returns></returns>
        public static int GetTimePosByTimeStr(this string time)
        {
            if (time?.Contains(":") ?? false)
            {
                var strs = time.Split(':');
                var hour = int.Parse(strs[0]);
                var minute = int.Parse(strs[1]);
                return hour.GetTimePosByHour() + minute;
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// 获得两个时间块相交时间块 
        /// </summary>
        /// <param name="start1"></param>
        /// <param name="end1"></param>
        /// <param name="start2"></param>
        /// <param name="end2"></param>
        /// <param name="startOut"></param>
        /// <param name="endOut"></param>
        /// <returns></returns>
        public static bool GetOverlapTime(int start1, int end1, int start2, int end2, out int startOut, out int endOut)
        {
            startOut = start1;
            endOut = end1;
            if (start1 <= end2 && start2 <= end1)
            {
                startOut = Math.Max(start1, start2);
                endOut = Math.Min(end1, end2);
                return true;
            }

            return false;
        }

        /// <summary>
        /// 计算时间段1是否在时间段2上
        /// </summary>
        /// <param name="start1"></param>
        /// <param name="end1"></param>
        /// <param name="start2"></param>
        /// <param name="end2"></param>
        /// <returns></returns>
        public static bool CalIn(int start1, int end1, int start2, int end2)
        {
            int sO;
            int eO;
            return GetOverlapTime(start1, end1, start2, end2, out sO, out eO) && sO == start1 && eO == end1;
        }

        public static bool GetEarliestTimePos(int s1, int e1, int s2, int e2, int time1, int time2, int startPos, out int timePos, int t2Tot1dis = 0)
        {
            int sO;
            int eO;
            timePos = 0;
            //1.取得上下两个时间块相交区域
            //2.遍历相交区域的尝试放入下面的时间块，因为从上面时间块占用时间后开始搜索即上面时间块可以放入
            if (GetOverlapTime(s1, e1 + t2Tot1dis, s2, e2, out sO, out eO) && e1 - s1 > time1 && e2 - s2 > time2)
            {
                var start = Math.Max(s1 + time1 + t2Tot1dis, sO);
                start = Math.Max(start, startPos);
                var end = eO;
                for (int i = start; i < end; i++)
                {
                    //洗车任务时间为start - time1 - t2Tot1dis, start - t2Tot1dis
                    //检修任务时间为start, start + time2
                    if (CalIn(i - time1 - t2Tot1dis, i - t2Tot1dis, s1, e1) && CalIn(i, i + time2, s2, e2))
                    {
                        timePos = i;
                        return true;
                    }
                }
            }

            return false;
        }

        public static bool GetEarliestTimePos(List<int> pos, int safe, int s1, int e1, int s2, int e2, int time0, int time1, int time2, int startPos, out int timePos, int t2Tot1dis = 0)
        {
            int sO;
            int eO;
            timePos = 0;
            //1.取得上下两个时间块相交区域
            //2.遍历相交区域的尝试放入下面的时间块，因为从上面时间块占用时间后开始搜索即上面时间块可以放入
            if (GetOverlapTime(s1, e1 + t2Tot1dis, s2, e2, out sO, out eO) && e1 - s1 > time1 && e2 - s2 > time2)
            {
                var start = Math.Max(s1 + time1 + t2Tot1dis, sO);
                start = Math.Max(start, startPos);
                var end = eO;
                for (int i = start; i < end; i++)
                {
                    //洗车任务时间为start - time1 - t2Tot1dis, start - t2Tot1dis
                    //检修任务时间为start, start + time2
                    if (
                        CalIn(i - time1 - t2Tot1dis, i - t2Tot1dis, s1, e1)
                        && CalIn(i, i + time2, s2, e2)
                        && pos.All(x => Math.Abs(i - x) >= safe)
                        )
                    {
                        timePos = i;
                        return true;
                    }
                }
            }

            return false;
        }
    }
}